package com.intretech.tj.gpp


import com.google.gson.Gson
import com.google.gson.JsonSyntaxException
import com.google.gson.reflect.TypeToken
import com.intretech.tj.global.tools.JSONTool
import com.intretech.tj.gpp.entity.DTO.*
import com.intretech.tj.gpp.entity.DTO.Vehicle.VehicleStatus
import com.intretech.tj.gpp.entity.DTO.Vehicle.VehicleTaskInfo
import com.intretech.tj.gpp.entity.DTO.light.TrafficLightInfo
import com.intretech.tj.gpp.result.TaskResult
import com.intretech.tj.gpp.service.GPPService
import com.intretech.tj.mqtt.MQTTVerticle
import com.intretech.tj.mqtt.trigger.TopicMessageTrigger
import io.quarkus.scheduler.Scheduled
import io.smallrye.mutiny.vertx.core.AbstractVerticle
import io.vertx.core.Promise
import jakarta.enterprise.context.ApplicationScoped
import jakarta.inject.Inject
import org.slf4j.LoggerFactory
import java.nio.charset.StandardCharsets

/**
 * GPP(Global Path Planning)服务的Verticle实现
 * 负责处理车辆路径规划、状态更新和路段管理等功能
 */
@ApplicationScoped
class GPPVerticle @Inject constructor(
    private val gppService: GPPService,
    private val mqttVerticle: MQTTVerticle, // MQTT消息发布服务
    private val topicMessageTrigger: TopicMessageTrigger, // MQTT消息订阅服务
    private val config: GppConfig
) : AbstractVerticle() {


    private val logger = LoggerFactory.getLogger(GPPVerticle::class.java)

    /**
     * Verticle启动时执行的初始化方法
     */
    override fun start(startPromise: Promise<Void>?) {
        logger.info("开始初始化地图")
        gppService.initMap()

        // 注册所有MQTT消息处理器
        registerPathRequestHandler()
        registerVehicleStatusHandler()
        registerEdgeSettingHandler()
        registerLightStatusHandler()
        registerMapStatusHandler()
    }

    /**
     * 注册路径请求处理器
     * 处理车辆发送的路径规划请求
     */
    private fun registerPathRequestHandler() {
        topicMessageTrigger.setTrigger(
            config.newPathTopic(),
            logger.name
        ) { idAndMessage: TopicMessageTrigger.IDAndMessage ->
            // 解析JSON数据
            val message = idAndMessage.message().payload().toString(StandardCharsets.UTF_8)
            if (!message.contains("currentNodeId")) {
                logger.warn("收到无效的路径请求消息：缺少currentNodeId字段")
                return@setTrigger
            }

            try {
                val pathRequest: PathRequest = Gson().fromJson(
                    message,
                    PathRequest::class.java
                )

                // 获取规划任务信息(车辆ID + UUID + UUID_topic)
                val vehicleTaskInfo = gppService.getVehicleTaskInfo(pathRequest)

                // 发送规划任务信息给车辆
                mqttVerticle.publish(
                    config.newPathTopic(),
                    0,
                    JSONTool.toJSONString(vehicleTaskInfo)
                )

                // 注册车辆任务处理器
                registerVehicleTaskHandler(vehicleTaskInfo, pathRequest)
            } catch (e: Exception) {
                logger.error("处理路径请求失败", e)
            }
        }
    }

    /**
     * 注册车辆任务处理器
     * 处理特定车辆的任务响应
     */
    private fun registerVehicleTaskHandler(vehicleTaskInfo: VehicleTaskInfo, pathRequest: PathRequest) {
        topicMessageTrigger.setTrigger(
            config.taskTopicPrefix() + vehicleTaskInfo.taskTopic,
            logger.name
        ) { idAndMessage: TopicMessageTrigger.IDAndMessage ->
            try {
                val taskMessage = idAndMessage.message().payload().toString(StandardCharsets.UTF_8)
                val vehicleTask: VehicleTaskInfo = Gson().fromJson(
                    taskMessage,
                    VehicleTaskInfo::class.java
                )

                // 验证任务Topic是否有效
                if (!gppService.isValidTaskTopic(vehicleTask.taskTopic, vehicleTask.vehicleId)) {
                    logger.warn("收到无效的任务Topic: ${vehicleTask.taskTopic} 对应车辆: ${vehicleTask.vehicleId}")
                    return@setTrigger
                }

                // 初始化车辆状态并规划路径
                val requestPath = gppService.requestPath(pathRequest)
                if (requestPath.isNullOrEmpty()) {
                    logger.warn("无法为车辆 ${pathRequest.vehicleId} 规划有效路径")
                    return@setTrigger
                }

                // 获取并发送车辆消息
                val vehicleMessage = gppService.getVehicleMessage(requestPath, pathRequest, vehicleTaskInfo.taskId)
                mqttVerticle.publish(
                    config.taskTopicPrefix() + vehicleTaskInfo.taskTopic,
                    0,
                    JSONTool.toJSONString(vehicleMessage)
                )
            } catch (e: Exception) {
                logger.error("处理车辆任务失败", e)
            }
        }
    }

    /**
     * 注册车辆状态处理器
     * 处理车辆上报的状态信息
     */
    private fun registerVehicleStatusHandler() {
        topicMessageTrigger.setTrigger(
            config.vehicleStatusTopic(),
            logger.name
        ) { idAndMessage: TopicMessageTrigger.IDAndMessage ->
            try {
                // 解析车辆状态消息
                val vehicleState: VehicleStatus = Gson().fromJson(
                    idAndMessage.message().payload().toString(StandardCharsets.UTF_8),
                    VehicleStatus::class.java
                )

                // 更新车辆状态并获取结果
                when (val taskResult = gppService.updateVehicle(vehicleState)) {
                    is TaskResult.SuccessEnd -> {
                        // 车辆到达终点
                        mqttVerticle.publish(
                            config.taskTopicPrefix() + taskResult.taskTopic,
                            0,
                            JSONTool.toJSONString(taskResult.result)
                        )
                        logger.info("车辆 ${vehicleState.vehicleId} 已到达终点")
                    }

                    is TaskResult.Success -> {
                        // 车辆正常行驶中
                        mqttVerticle.publish(
                            config.taskTopicPrefix() + taskResult.taskTopic,
                            0,
                            JSONTool.toJSONString(taskResult.result)
                        )
                    }

                    is TaskResult.NotFound -> {
                        // 车辆未注册或未找到
                        logger.debug("未找到车辆 ${vehicleState.vehicleId} 的注册信息")
                        return@setTrigger
                    }
                }
            } catch (e: Exception) {
                logger.error("处理车辆状态更新失败", e)
            }
        }
    }

    /**
     * 注册路段设置处理器
     * 处理路段启用/禁用的请求
     */
    private fun registerEdgeSettingHandler() {
        topicMessageTrigger.setTrigger(
            config.edgeSettingTopic(),
            logger.name
        ) { idAndMessage: TopicMessageTrigger.IDAndMessage ->
            try {
                logger.info("收到路段设置请求")
                val edgeStatusUpdate: EdgeStatusUpdate = Gson().fromJson(
                    idAndMessage.message().payload().toString(StandardCharsets.UTF_8),
                    EdgeStatusUpdate::class.java
                )

                // 调用 gppService 处理路段状态更新
                val result = gppService.disableOrEnableEdge(edgeStatusUpdate)

                // 只有当 result 不为 null 时才发送 MQTT 消息
                if (result != null) {
                    try {
                        mqttVerticle.publish(
                            config.vehicleAvoidanceTopic(),
                            0,
                            JSONTool.toJSONString(result) // 确保这里传递的是 result
                        )
                    } catch (e: Exception) {
                        logger.error("发送车辆信息失败", e)
                    }
                } else {
                    logger.warn("gppService.disableOrEnableEdge 返回 null，跳过发送车辆状态信息。")
                }

                logger.info("路段 ${edgeStatusUpdate.edgeId} ${if (edgeStatusUpdate.disabled) "已禁用" else "已启用"}")

            } catch (e: JsonSyntaxException) {
                // JSON 解析异常
                logger.error("解析路段设置请求JSON失败", e)
            } catch (e: Exception) {
                // 其他未知异常
                logger.error("处理路段设置请求时发生未知错误", e)
            }
        }
    }

    /**
     * 定时接收所有路灯信息
     * 每 1秒接收一次
     */
    private fun registerLightStatusHandler() {
        topicMessageTrigger.setTrigger(
            "device/light/tcp",
            logger.name
        ) { idAndMessage: TopicMessageTrigger.IDAndMessage ->
            try {
                logger.info("收到路灯设置请求")
                val lightList: List<TrafficLightInfo> = Gson().fromJson(
                    idAndMessage.message().payload().toString(StandardCharsets.UTF_8),
                    object : TypeToken<List<TrafficLightInfo>>() {}.type
                )
                //TODO 处理路灯信息
                //gppService.updateTrafficLightStatus()
            } catch (e: Exception) {
                logger.error("处理路段设置失败", e)
            }
        }
    }

    /**
     * 定时发送所有车辆信息
     * 每1秒执行一次
     */
    @Scheduled(every = "1s")
    fun sendAllVehicleInformation() {
        try {
            mqttVerticle.publish(
                config.vehicleStatusAllTopic(),
                0,
                JSONTool.toJSONString(gppService.getAllVehicle())
            )
        } catch (e: Exception) {
            logger.error("发送车辆信息失败", e)
        }
    }

    /**
     * 定时发送地图信息
     * 每1秒执行一次
     */
    @Scheduled(every = "1s")
    fun registerMapStatusHandler() {
        try {
            mqttVerticle.publish(
                config.mapStatusAllTopic(),
                0,
                JSONTool.toJSONString(gppService.getMapInfo())
            )
        } catch (e: Exception) {
            logger.error("发送地图信息失败", e)
        }
    }
}